/* Includes ------------------------------------------------------------------*/
#include "si2c.h"

////////////////////////////////////////////////////////////////////////////////
/// @brief  Clock and data bus configuration
/// @note   Keep the bus free which means SCK & SDA is high.
/// @param  : None.
/// @retval : None.
////////////////////////////////////////////////////////////////////////////////
#define POLYNOMIAL 	0x131 //100110001
unsigned char MY_I2C_CRC8(unsigned char Data[], unsigned char nbrOfBytes){
  unsigned char BIT;        // bit mask
  unsigned char crc = 0xFF; // calculated checksum
  unsigned char byteCtr;    // byte counter
  
  // calculates 8-Bit checksum with given polynomial
  for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++){
    crc ^= (Data[byteCtr]);
    for(BIT = 8; BIT > 0; --BIT){
      if(crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
      else           crc = (crc << 1);
    }
  }
  
  return crc;
}
 void I2C1_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_AHBPeriphClockCmd(GPIOI2C_SDA_BUSCLK, ENABLE);
    RCC_AHBPeriphClockCmd(GPIOI2C_SCL_BUSCLK, ENABLE);
    GPIO_PinAFConfig(GPIOI2C_SCL_GPIO_PORT, GPIO_PinSource5, GPIO_AF_3);
    GPIO_PinAFConfig(GPIOI2C_SDA_GPIO_PORT, GPIO_PinSource4, GPIO_AF_3);

    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin  = GPIOI2C_SCL_PIN;
    //Set GPIO spped
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    //Keep the bus free which means SCK & SDA is high
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOI2C_SCL_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin  = GPIOI2C_SDA_PIN;
		GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOI2C_SDA_GPIO_PORT, &GPIO_InitStruct);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief  Initializes the I2Cx master mode
/// @note   None.
/// @param  : I2Cx (where x can be 1 or 2 to select the I2C peripheral)
/// @param  : iI2C_speed: I2C speed.
/// @retval : None.
////////////////////////////////////////////////////////////////////////////////
void I2C_MasterModeInit(I2C_TypeDef* I2Cx, u32 uiI2C_speed)
{
    I2C_InitTypeDef I2C_InitStruct;

    //Enable I2C clock state
    RCC_APB1PeriphClockCmd(RCC_APB1ENR_I2C1, ENABLE);

    I2C_StructInit(&I2C_InitStruct);
    //Configure I2C as master mode
    I2C_InitStruct.Mode = I2C_CR_MASTER;
    I2C_InitStruct.OwnAddress = 0;
    I2C_InitStruct.Speed = I2C_CR_STD;
    I2C_InitStruct.ClockSpeed = uiI2C_speed;
	
    //Initializes the I2Cx peripheral according to the specified
    I2C_Init(I2Cx, &I2C_InitStruct);

    I2C_Cmd(I2Cx, ENABLE);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief  Set the device address
/// @note   None.
/// @param  : I2Cx(where x can be 1 or 2 to select the I2C peripheral)
/// @param  : deviceaddr(device address).
/// @retval : None.
////////////////////////////////////////////////////////////////////////////////
void I2C_SetDeviceAddr(I2C_TypeDef* I2Cx, u8 deviceaddr)
{
    I2C_Cmd(I2Cx, DISABLE);
    I2C_Send7bitAddress(I2Cx, deviceaddr, I2C_Direction_Transmitter);
    I2C_Cmd(I2Cx, ENABLE);
}

void I2C_HardInit(void)
{
    I2C1_GPIO_Config();
    //Initializes the I2C master mode
    I2C_MasterModeInit(I2C1, 300000);
    //Set the EEPROM address
    I2C_SetDeviceAddr(I2C1, IIC_ADDR);
}

/**************************************/
u8 iic_write_anyreg(unsigned char DeviceAddr, MC1081_REG RegAddr, unsigned char Data)
{
	u32 timeout=100000;
	uint8_t addr,value,ERROR_IIC=0;;
	addr = RegAddr;
	value = Data;
	I2C_ClearFlag(I2C1,I2C_FLAG_STOP_DET);
	I2C_SendData(I2C1, addr);
	while((I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE) == 0)&&timeout>0)
	{
		timeout--;
	}
	Delay_us(100);
	if(I2C_GetITStatus(I2C1, I2C_IT_STOP_DET)==1)
	{
		I2C_GenerateSTOP(I2C1, ENABLE);
		while(((I2C_GetITStatus(I2C1, I2C_IT_STOP_DET)) == 0)&&timeout>0)
		{
			timeout--;
		}
		timeout=100000;
		ERROR_IIC=1;
	}
	timeout=100000;
	I2C_ClearFlag(I2C1,I2C_FLAG_STOP_DET);
	Delay_us(100);
	I2C_SendData(I2C1, value);
	while((I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE) == 0)&&timeout>0)
	{
		timeout--;
	}
	Delay_us(100);
	if(I2C_GetITStatus(I2C1, I2C_IT_STOP_DET)==1)
	{
		I2C_GenerateSTOP(I2C1, ENABLE);
		while(((I2C_GetITStatus(I2C1, I2C_IT_STOP_DET)) == 0)&&timeout>0)
		{
			timeout--;
		}
		timeout=100000;
		ERROR_IIC=1;
	}
	timeout=100000;
	I2C_GenerateSTOP(I2C1, ENABLE);
	while(((I2C_GetITStatus(I2C1, I2C_IT_STOP_DET)) == 0)&&timeout>0)
	{
		timeout--;
	}
	timeout=100000;
}
/************************************************/
u8 iic_read_anyreg(unsigned char DeviceAddr, MC1081_REG RegAddr,unsigned char *pData,unsigned char size)
{
	u32 timeout=100000;
	uint8_t addr,len,flag=0,i;
	addr = RegAddr;
	len = size;
//		PR("\r\n addr  %02X  len %d",addr,len);
	for(i=0;i<len;i++)
	{
		I2C_ClearFlag(I2C1,I2C_FLAG_STOP_DET);
		I2C_SendData(I2C1, addr);
		addr+=1;
		//Checks whether transmit FIFO completely empty or not
		while((I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE) == 0)&&timeout>0)
		{

			timeout--;
		}
		Delay_us(100);
		if(I2C_GetITStatus(I2C1, I2C_IT_STOP_DET)==1)
		{
			I2C_GenerateSTOP(I2C1, ENABLE);
		//Checks whether stop condition has occurred or not.
			while(((I2C_GetITStatus(I2C1, I2C_IT_STOP_DET)) == 0)&&timeout>0)
			{
				timeout--;
			}
			timeout=100000;

			return 0;
		}
		timeout=100000;
		//Stop transmission
		I2C_GenerateSTART(I2C1, ENABLE);
		//Checks whether stop condition has occurred or not.
		while(((I2C_GetITStatus(I2C1, I2C_IT_START_DET)) == 0)&&timeout>0)
		{
			timeout--;
		}
		timeout=100000;
		while(1) 
		{
			
				//Write command is sent when RX FIFO is not full
				if ((I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFNF)) && (flag == 0)) 
				{
					I2C_ClearFlag(I2C1,I2C_FLAG_STOP_DET);
						//Configure to read
						I2C_ReadCmd(I2C1);	
						flag = 1;
				}
				
				//Check receive FIFO not empty
				if (I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_RFNE)) {
						//read data to gEeprom.ptr
						pData[i] = I2C_ReceiveData(I2C1);
						break;
				}
				else
				{
					timeout--;
					if(timeout<=0)break;
				}
				if((I2C_GetITStatus(I2C1, I2C_IT_STOP_DET) == 1) )
				{
					I2C_GenerateSTOP(I2C1, ENABLE);
				//Checks whether stop condition has occurred or not.
					while(((I2C_GetITStatus(I2C1, I2C_IT_STOP_DET)) == 0)&&timeout>0)
					{
						timeout--;
					}
					timeout=100000;

					return 0;
				}
		}
		timeout=100000;
		I2C_GenerateSTOP(I2C1, ENABLE);
	//Checks whether stop condition has occurred or not.
		while(((I2C_GetITStatus(I2C1, I2C_IT_STOP_DET)) == 0)&&timeout>0)
		{
			timeout--;
		}
		timeout=100000;
		flag=0;
	}
//	PR(" Succuess");
	return 1;
}

